package com.thinkit.cms.service.fragment;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.thinkit.cms.api.fragment.FragmentAttrService;
import com.thinkit.cms.api.fragment.FragmentModelService;
import com.thinkit.cms.dto.fragment.FragmentAttrDto;
import com.thinkit.cms.entity.fragment.FragmentAttr;
import com.thinkit.cms.mapper.fragment.FragmentAttrMapper;
import com.thinkit.core.annotation.SiteMark;
import com.thinkit.core.base.BaseServiceImpl;
import com.thinkit.core.constant.Constants;
import com.thinkit.core.handler.CustomException;
import com.thinkit.utils.model.ApiResult;
import com.thinkit.utils.model.DynamicModel;
import com.thinkit.utils.model.PageDto;
import com.thinkit.utils.utils.Checker;
import com.thinkit.utils.utils.ModelFieldUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 页面片段数据表 服务实现类
 * </p>
 *
 * @author lg
 * @since 2020-08-03
 */
@Transactional
@Service
public class FragmentAttrServiceImpl extends BaseServiceImpl<FragmentAttrDto, FragmentAttr, FragmentAttrMapper> implements FragmentAttrService {

    @Autowired
    private FragmentModelService fragmentModelService;



    @SiteMark
    @PostMapping("page")
    public PageDto<FragmentAttrDto> listPage(PageDto<FragmentAttrDto> pageDto){
        if(Checker.BeNotNull(pageDto.getDto())){
            String id = getId(pageDto.getDto().getFragmentModelId());
            pageDto.getDto().setFragmentModelId(id);
        }
        IPage<FragmentAttr> pages = new Page<>(pageDto.getPageNo(), pageDto.getPageSize());
        IPage<FragmentAttr> result = baseMapper.listPage(pages, pageDto.getDto());
        if(Checker.BeNotEmpty(result.getRecords())){

        }
        PageDto<FragmentAttrDto> resultSearch = new PageDto(result.getTotal(), result.getPages(), result.getCurrent(), Checker.BeNotEmpty(result.getRecords()) ? result.getRecords() : Lists.newArrayList());
        return resultSearch;
    }



    @SiteMark
    @Override
    public void insertFragmentAttr(FragmentAttrDto fragmentAttrDto) {
        if(Checker.BeBlank(fragmentAttrDto.getFragmentModelId())){
            throw new CustomException(ApiResult.result(5029));
        }
        String id = getId(fragmentAttrDto.getFragmentModelId());
        fragmentAttrDto.setFragmentModelId(id);
        filterFragmentAttr(fragmentAttrDto.getParams(),id,fragmentAttrDto);
        FragmentAttr fragmentAttr =D2T(fragmentAttrDto);
        if(Checker.BeNotEmpty(fragmentAttrDto.getCover())){
            fragmentAttr.setCover(JSONUtil.toJsonStr(fragmentAttrDto.getCover()));
        }
        baseMapper.insert(fragmentAttr);
    }


    @SiteMark
    @Override
    public void updateFragmentAttr(FragmentAttrDto fragmentAttrDto) {
          if(Checker.BeBlank(fragmentAttrDto.getId())){
              throw  new CustomException(ApiResult.result(5029));
          }
          filterFragmentAttr(fragmentAttrDto.getParams(),fragmentAttrDto.getFragmentModelId(),fragmentAttrDto);
          FragmentAttr fragmentAttr =D2T(fragmentAttrDto);
          if(Checker.BeNotEmpty(fragmentAttrDto.getCover())){
            fragmentAttr.setCover(JSONUtil.toJsonStr(fragmentAttrDto.getCover()));
          }
          baseMapper.updateById(fragmentAttr);
    }

    @Override
    public List<Map> listDataByCode(String code) {
        List<Map> datas = baseMapper.listDataByCode(code);
        filterListMap(datas);
        return Checker.BeNotEmpty(datas)?datas:Lists.newArrayList();
    }

    private void filterListMap(List<Map> maps){
        if(Checker.BeNotEmpty(maps)){
            for(Map map:maps){
                ModelFieldUtil.formatData(map);
                ModelFieldUtil.formatCover(map,true);
            }
        }
    }

    @Override
    public List<DynamicModel> getFragmentAttr(String id) {
        List<DynamicModel> resultFields =new ArrayList<>();
        FragmentAttrDto attrDto = super.getByPk(id);
        if(Checker.BeNotNull(attrDto)){
            String allFieldStrList =fragmentModelService.getFragmentFieldListJsonStr(id,0);
            if(Checker.BeNotNull(attrDto.getData())){
                List<DynamicModel> extendField= ModelFieldUtil.jsonStrToModel(attrDto.getData());
                resultFields.addAll(extendField);
            }
            if(Checker.BeNotBlank(allFieldStrList)){
                filterCheckField(resultFields,allFieldStrList,attrDto);
            }
            return resultFields;
        }else{
            return Lists.newArrayList();
        }
    }

    @Override
    public Map<String, Object> getDesignAttrById(String id) {
        Map<String,Object> result =new HashMap<>();
        List<DynamicModel> resultFields =new ArrayList<>();
        FragmentAttr attr =baseMapper.selectById(id);
        String cover = null;
        if(Checker.BeNotNull(attr) && Checker.BeNotBlank(attr.getFragmentModelId())){
            if(Checker.BeNotBlank(attr.getCover())){
                cover = attr.getCover();
                attr.setCover(null);
            }
            FragmentAttrDto attrDto = T2D(attr);
            if(Checker.BeNotBlank(cover)){
                List<Map> covers = JSONUtil.toList(JSONUtil.parseArray(cover),Map.class);
                attrDto.setCover(covers);
            }
            String allFieldStrList =fragmentModelService.getFragmentFieldListJsonStr(attr.getFragmentModelId(),0);
            if(Checker.BeNotBlank(allFieldStrList)){
               List<DynamicModel>  defaultFields=  ModelFieldUtil.listDefaultModel(allFieldStrList);
               if(Checker.BeNotEmpty(defaultFields)){
                   ModelFieldUtil.setFieldVal(defaultFields,attrDto,true);
                   resultFields.addAll(defaultFields);
               }
            }
            if(Checker.BeNotBlank(attrDto.getData())){
                List<DynamicModel>  extendFields=  ModelFieldUtil.jsonStrToModel(attrDto.getData());
                if(Checker.BeNotEmpty(extendFields)){
                    resultFields.addAll(extendFields);
                }
            }
        }
        result.put("data",attr);
        result.put("models",resultFields);
        return result;
    }



    private List<DynamicModel>  filterCheckField(List<DynamicModel> resultFields,String checkAllJson, FragmentAttrDto attrDto){
          if(Checker.BeNotBlank(checkAllJson)){
              List<DynamicModel> defaultModels= ModelFieldUtil.listDefaultModel(checkAllJson);
              if(Checker.BeNotEmpty(defaultModels)){
                  ModelFieldUtil.setFieldVal(defaultModels,attrDto,true);
                  resultFields.addAll(defaultModels);
              }
          }
          return resultFields;
    }

    private void filterFragmentAttr(Map<String,Object> params, String id, FragmentAttrDto fragmentAttrDto){
        String fieldJsonStr =fragmentModelService.getFragmentFieldListJsonStr(id,0);
        List<DynamicModel> extendFields = ModelFieldUtil.listExtendModel(fieldJsonStr);
        if(Checker.BeNotEmpty(extendFields)){
            for(DynamicModel dynamicModel:extendFields){
                Object data = getMapData(params,dynamicModel.getFieldCode());
                if(Checker.BeNotNull(data)){
                    dynamicModel.setDefaultValue(data);
                }
            }
            fragmentAttrDto.setData(ModelFieldUtil.modelToJsonStr(extendFields));
        }
    }

    private String getId(String fileName){
        if(Checker.BeNotBlank(fileName)){
            String id =fileName.replace(Constants.DEFAULT_FRAGMENT_PREFIX,"").
                    replace(Constants.DEFAULT_HTML_SUFFIX,"");
            return id;
        }
        return "";
    }

    private Object getMapData(Map<String,Object> params,String code){
        if(params.containsKey(code)){
            Object data = params.get(code);
            if(Checker.BeNotNull(data)){
                return data;
            }else{
                return "";
            }
        }else{
            return null;
        }
    }
}
